/*
 * ipcamera.c
 *
 *  Created on: 2013-4-16
 *      Author: root
 */

#include "ipcamera.h"

/* connect_server - 连接到IpCamera
 * @ ip 	-  IPCamera 的IP地址
 * @ port	-  IPCamera 的端口
 * @ return	-  连接成功时返回socket描述符号，错误时返回-1
 * */
int connect_server(const char *ip, unsigned short port){
	int cfd = -1;
	struct sockaddr_in saddr;
	int ret = -1;

	cfd = socket(PF_INET, SOCK_STREAM, 0);
	if (cfd == -1) {
		fprintf(stderr, "socket: %s\n", strerror(errno));
		return cfd;
	}
	bzero(&saddr, sizeof saddr);
	saddr.sin_family = PF_INET;
	saddr.sin_port = htons(port);
	if (inet_pton(AF_INET, ip, &saddr.sin_addr) == -1) {
		fprintf(stderr,"inet_pton : %s\n", strerror(errno));
		return -1;
	}
	// connect to server
	ret = connect(cfd, (struct sockaddr*)&saddr, sizeof (struct sockaddr));
	if (ret < 0) {
		fprintf(stderr, "connect : %s\n",strerror(errno));
		return -1;
	}
	return cfd;
}

/* read_line - 从指定到描述符号中读取一行数据，以\n作为结束标记，含换行
 * @ fd  - 指定到描述符号
 * @ buf - 缓冲，读取到数据存放
 * @ size - 缓冲区的大小
 * @ return - 返回读取到字节数，包含换行
 */
ssize_t	read_line(int fd, void *buf, size_t size) {
	int nbytes = 0;
	int ntotal = 0;
	char *mbuf;
	char ch;

	if (buf == NULL || size == 0) {
		errno = EINVAL;
		return -1;
	}
	mbuf = (char*)buf;
	ntotal = 0;
	while (1) {
		nbytes = read(fd, &ch, 1);
		if (nbytes == -1) {
			if (errno == EINTR)continue;
			else return -1;
		} else if (nbytes == 0){
			if (ntotal == 0) return 0;
			else break;
		} else {
			if (ntotal < size-1) {
				ntotal++;
				*mbuf++ = ch;
			}
			if (ch == '\n') break;
		}
	}
	*mbuf = '\0';
	//printf("%s\n", mbuf);
	return ntotal;
}

/* read_header 	- 读取信息头，以空行作为结束
 * @fd 			- 指定描述符号
 * @header		- 数据存放
 * @size		- header的大小，默认size足够大，size过小时取读不准确
 * @return 		- 总取读字节数
 */
ssize_t read_header (int fd, void *header, size_t size) {
	char *mbuf = (char*)header;
	char line[1024] = {};
	int nbytes = 0;
	int ntotal = 0;
	for (;;) {
		nbytes = read_line(fd, line, 1024);
		//printf("read_header: %s\n", line);
		if (nbytes == 0) return 0;
		if (strncmp(line,"\r\n", 2) == 0) {
			return ntotal+2;
		}
		ntotal += nbytes;
		strcat(mbuf,line);
	}
	//printf("%s\n", mbuf);
	return 0;
}


/* mkrequest	- 构建一个向IpCamera的请求
 * @request 	- 存放请求的buf
 * @len			- buf的大小
 * @get			- 使用GET 获取的内容
 * @host		- 连接的主机 格式: "192.168.1.198:33"
 * */
int mkrequest(char *request, int len, const char *get, const char *host) {
	memset(request, 0 , len);
	char mhost[30] = {};
	sprintf(request, "GET %s HTTP/1.1\r\n", get);
	sprintf(mhost, "Host :%s\r\n",host);
	strcat(request, mhost);
//    strcat(request, "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:20.0) Gecko/20100101 Firefox/20.0\r\n");
//    strcat(request, "Accept: image/png,image/*;q=0.8,*/*;q=0.5\r\n");
//    strcat(request, "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n");
//    strcat(request, "Accept-Encoding: gzip, deflate\r\n");
//    strcat(request, "Referer: http://192.168.1.198:33/stream.htm\r\n");
//    strcat(request, "Cookie: bShowMenu=1\r\n");
    strcat(request, "Connecttion: keep-alive\r\n\r\n");
	return 0;
}

/* parse_content_length - 解析数据头，得到真实的有效数据长度
 * @str		- 数据头		Content-Length: 2220
 * @return  - 数据长度
 * */
int parse_content_length(const char *str) {
	int num = strlen(str);
	char *src = malloc (num+1);
	char *tmp;
	strcpy(src, str);
	tmp = strtok(src, "\n");
	while (1) {
		tmp = strtok(NULL, "\n");
		if (strncmp(tmp, "Content-Length:", strlen("Content-Length:")) == 0) {
			break;
		}
	}
	tmp = strtok(tmp, " ");
	tmp = strtok(NULL, " ");
	num = atoi(tmp);
	return num;
}

/* read_data - 读取有效到数据存储到文件中
 * @fd 		-描述符
 * @ file 	- 文件名
 * @ size	- 数据长度
 * */
int read_data(int sfd, const char *file, size_t size) {
	int num = 0 ;
	int ntotal = 0;
	int err = 0;
	FILE *f = NULL;
	f = fopen(file, "w");
	if (f == NULL) {
		printf("fopen : %m\n");
		return -1;
	}
	char buf;
	while (ntotal <= size) {
		num = recv(sfd, &buf, 1, MSG_WAITALL);
		if (num <= 0) {
			break;
		}
		ntotal += num;
		err = fwrite (&buf, 1, num, f);
		if (err < 0) {
			printf("\nwrite:%m\n");
		}
		//buf[num] = '\0';
		//printf("%s", buf);
	}
	fclose(f);
	return ntotal;
}




